import { describe, test, expect, beforeAll, afterAll } from 'bun:test';
import type { Server } from 'bun';

describe('Sub-Agents E2E Tests', () => {
  let server: Server;
  const baseUrl = 'http://localhost:3001'; // Use different port for testing

  beforeAll(async () => {
    // Initialize SubAgentManager
    const { initializeSubAgentManager, builtinSubAgents } = await import('../src/subagents');
    const { skillsManager } = await import('../src/skills');

    const subAgentManager = initializeSubAgentManager(skillsManager);
    subAgentManager.registerSubAgents(builtinSubAgents);

    // Start test server
    const { createApp } = await import('../src/api/server');
    const app = createApp();

    server = Bun.serve({
      port: 3001,
      hostname: 'localhost',
      fetch: app.fetch,
      idleTimeout: 255,
    });

    // Wait for server to be ready
    await new Promise(resolve => setTimeout(resolve, 100));
  });

  afterAll(() => {
    if (server) {
      server.stop();
    }
  });

  describe('API Integration', () => {
    test('should list all sub-agents including builtin', async () => {
      const response = await fetch(`${baseUrl}/api/subagents`);
      const data = await response.json();

      expect(response.status).toBe(200);
      expect(data.success).toBe(true);
      expect(data.data.subagents).toBeArray();
      expect(data.data.subagents.length).toBeGreaterThanOrEqual(8); // At least 8 builtin
      expect(data.data.stats).toBeDefined();
      expect(data.data.stats.total).toBeGreaterThanOrEqual(8);
      expect(data.data.stats.builtin).toBe(8);
    });

    test('should create, update, and delete custom sub-agent', async () => {
      const customAgent = {
        id: 'e2e-test-agent',
        name: 'E2E Test Agent',
        description: 'Agent for end-to-end testing',
        prompt: 'You are a test agent',
        tools: ['Read', 'Write'],
        model: 'sonnet' as const,
        category: 'testing' as const,
      };

      // Create
      const createResponse = await fetch(`${baseUrl}/api/subagents`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(customAgent),
      });
      const createData = await createResponse.json();

      expect(createResponse.status).toBe(201);
      expect(createData.success).toBe(true);

      // Read
      const getResponse = await fetch(`${baseUrl}/api/subagents/${customAgent.id}`);
      const getData = await getResponse.json();

      expect(getResponse.status).toBe(200);
      expect(getData.success).toBe(true);
      expect(getData.data.id).toBe(customAgent.id);
      expect(getData.data.name).toBe(customAgent.name);

      // Update
      const updateResponse = await fetch(`${baseUrl}/api/subagents/${customAgent.id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name: 'Updated E2E Test Agent' }),
      });
      const updateData = await updateResponse.json();

      expect(updateResponse.status).toBe(200);
      expect(updateData.success).toBe(true);
      expect(updateData.data.name).toBe('Updated E2E Test Agent');

      // Delete
      const deleteResponse = await fetch(`${baseUrl}/api/subagents/${customAgent.id}`, {
        method: 'DELETE',
      });
      const deleteData = await deleteResponse.json();

      expect(deleteResponse.status).toBe(200);
      expect(deleteData.success).toBe(true);

      // Verify deletion
      const verifyResponse = await fetch(`${baseUrl}/api/subagents/${customAgent.id}`);
      const verifyData = await verifyResponse.json();

      expect(verifyResponse.status).toBe(404);
      expect(verifyData.success).toBe(false);
    });

    test('should get SDK-compatible configuration', async () => {
      const response = await fetch(`${baseUrl}/api/subagents/config/sdk`);
      const data = await response.json();

      expect(response.status).toBe(200);
      expect(data.success).toBe(true);
      expect(data.data).toBeDefined();
      expect(typeof data.data).toBe('object');

      // Check that configuration is not empty
      const keys = Object.keys(data.data);
      expect(keys.length).toBeGreaterThan(0);
    });

    test('should import and export sub-agents', async () => {
      const testAgents = [
        {
          id: 'import-test-1',
          name: 'Import Test 1',
          description: 'First import test agent',
          prompt: 'You are import test 1',
          model: 'sonnet' as const,
          category: 'testing' as const,
        },
        {
          id: 'import-test-2',
          name: 'Import Test 2',
          description: 'Second import test agent',
          prompt: 'You are import test 2',
          model: 'haiku' as const,
          category: 'testing' as const,
        },
      ];

      // Import
      const importResponse = await fetch(`${baseUrl}/api/subagents/import`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ subagents: testAgents, overwrite: false }),
      });
      const importData = await importResponse.json();

      expect(importResponse.status).toBe(200);
      expect(importData.success).toBe(true);
      expect(importData.data.success).toBe(2);
      expect(importData.data.failed).toBe(0);

      // Export
      const exportResponse = await fetch(`${baseUrl}/api/subagents/export`);
      const exportData = await exportResponse.json();

      expect(exportResponse.status).toBe(200);
      expect(exportData.success).toBe(true);
      expect(exportData.data).toBeArray();
      
      const exportedIds = exportData.data.map((agent: any) => agent.id);
      expect(exportedIds).toContain('import-test-1');
      expect(exportedIds).toContain('import-test-2');

      // Cleanup
      await fetch(`${baseUrl}/api/subagents/import-test-1`, { method: 'DELETE' });
      await fetch(`${baseUrl}/api/subagents/import-test-2`, { method: 'DELETE' });
    });
  });

  describe('Error Handling', () => {
    test('should handle invalid sub-agent creation', async () => {
      const invalidAgent = {
        // Missing required fields
        name: 'Invalid Agent',
      };

      const response = await fetch(`${baseUrl}/api/subagents`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(invalidAgent),
      });
      const data = await response.json();

      expect(response.status).toBe(400);
      expect(data.success).toBe(false);
    });

    test('should prevent deletion of builtin sub-agents', async () => {
      const response = await fetch(`${baseUrl}/api/subagents/code-reviewer`, {
        method: 'DELETE',
      });
      const data = await response.json();

      expect(response.status).toBe(400);
      expect(data.success).toBe(false);
      expect(data.error.message).toContain('builtin');
    });

    test('should handle non-existent sub-agent', async () => {
      const response = await fetch(`${baseUrl}/api/subagents/non-existent-agent`);
      const data = await response.json();

      expect(response.status).toBe(404);
      expect(data.success).toBe(false);
    });
  });

  describe('Performance', () => {
    test('should handle multiple concurrent requests', async () => {
      const requests = Array.from({ length: 10 }, () =>
        fetch(`${baseUrl}/api/subagents`).then((r) => r.json())
      );

      const results = await Promise.all(requests);

      results.forEach((data) => {
        expect(data.success).toBe(true);
        expect(data.data.subagents).toBeArray();
      });
    });

    test('should handle large import efficiently', async () => {
      const largeImport = Array.from({ length: 50 }, (_, i) => ({
        id: `perf-test-${i}`,
        name: `Performance Test ${i}`,
        description: `Performance test agent ${i}`,
        prompt: `You are performance test agent ${i}`,
        model: 'haiku' as const,
        category: 'testing' as const,
      }));

      const startTime = Date.now();
      const response = await fetch(`${baseUrl}/api/subagents/import`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ subagents: largeImport, overwrite: false }),
      });
      const endTime = Date.now();
      const data = await response.json();

      expect(response.status).toBe(200);
      expect(data.success).toBe(true);
      expect(data.data.success).toBe(50);
      expect(endTime - startTime).toBeLessThan(1000); // Should complete in less than 1 second

      // Cleanup
      for (let i = 0; i < 50; i++) {
        await fetch(`${baseUrl}/api/subagents/perf-test-${i}`, { method: 'DELETE' });
      }
    });
  });

  describe('Integration with Skills', () => {
    test('should associate sub-agent with skills', async () => {
      const agentWithSkills = {
        id: 'skills-test-agent',
        name: 'Skills Test Agent',
        description: 'Agent with skills association',
        prompt: 'You are a skills test agent',
        skillIds: ['code-generation'], // Assuming this skill exists
        model: 'sonnet' as const,
        category: 'development' as const,
      };

      const response = await fetch(`${baseUrl}/api/subagents`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(agentWithSkills),
      });
      const data = await response.json();

      expect(response.status).toBe(201);
      expect(data.success).toBe(true);

      // Verify skills association
      const getResponse = await fetch(`${baseUrl}/api/subagents/${agentWithSkills.id}`);
      const getData = await getResponse.json();

      expect(getData.data.skillIds).toContain('code-generation');

      // Cleanup
      await fetch(`${baseUrl}/api/subagents/${agentWithSkills.id}`, { method: 'DELETE' });
    });
  });
});

